﻿#pragma once

#include "common.h"
#include "ui.h"

namespace anip
{
	namespace ui
	{
		class Utility
		{
		public:
			template<class T>
			static T* findControl(Control& start)
			{
				// DFS
				Control* current = &start;
				T* ctrl = nullptr;
				std::set<Control*> visited;
				while (current != nullptr)
				{
					Control* c = nullptr;
					if (visited.count(current) == 0)
					{
						visited.insert(current);
						if (typeid(*current) == typeid(T))
						{
							ctrl = (T*)current;
							break;
						}
						c = ((Container*)current)->firstChild();
						if (c != nullptr) { current = c; continue; }
					}

					c = ((Container*)current)->next();
					if (c != nullptr) { current = c; continue; }

					current = ((Container*)current)->parent();
				}

				return ctrl;
			}

			template<class T, typename Pred>
			static T* findControl(Control& start, Pred p)
			{
				// DFS
				Control* current = &start;
				T* ctrl = nullptr;
				std::set<Control*> visited;
				while (current != nullptr)
				{
					Control* c = nullptr;
					if (visited.count(current) == 0)
					{
						visited.insert(current);
						if (typeid(*current) == typeid(T) && p(*(T*)current))
						{
							ctrl = (T*)current;
							break;
						}
						c = ((Container*)current)->firstChild();
						if (c != nullptr) { current = c; continue; }
					}

					c = ((Container*)current)->next();
					if (c != nullptr) { current = c; continue; }

					current = ((Container*)current)->parent();
				}

				return ctrl;
			}

			template<typename Pred>
			static Control* findControl(Control& start, Pred p)
			{
				// DFS
				Control* current = &start;
				Control* ctrl = nullptr;
				std::set<Control*> visited;
				while (current != nullptr)
				{

					Control* c = nullptr;
					if (visited.count(current) == 0)
					{
						visited.insert(current);
						if (p(*current))
						{
							ctrl = current;
							break;
						}
						c = ((Container*)current)->firstChild();
						if (c != nullptr) { current = c; continue; }
					}

					c = ((Container*)current)->next();
					if (c != nullptr) { current = c; continue; }

					current = ((Container*)current)->parent();
				}

				return ctrl;
			}
		};
	}
}